<template>
  <HeadContainer :title="$t('title.takePicture')" @back="goBack()">
    <div class="center">
      <Camera
        ref="camera"
        :autoplay="false"
        :playsinline="true"
        @loading="onLoading"
        @started="onStarted"
        @stopped="onStopped"
        @paused="onPaused"
        @resumed="onResumed"
        @camera-change="onCameraChanged"
        @snapshot="onSnapshot"
        @error="onError"
      >
        <template #default>
          <div>
            <div class="top-container" ref="topContainer"></div>
            <div class="bottom-container" ref="bottomContainer">
              <div class="controller">
                <button class="capture-button" @click="flipMirror">
                  <Icon size="32" name="flipHorizontal"></Icon>
                </button>
                <button class="capture-button" @click="camera.snapshot()">
                  <Icon size="32" name="camera"></Icon>
                </button>
                <button class="capture-button" @click="flipCamera">
                  <Icon size="32" :name="isFirstDevice ? 'cameraFlipOutline' : 'cameraFlip'"></Icon>
                </button>
              </div>
            </div>
          </div>
        </template>
      </Camera>
    </div>
  </HeadContainer>
</template>
<script setup>
import Camera from 'simple-vue-camera'
import { computed, onMounted, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useBecomeCreatorDataStore } from '@/store/become-creator-data'
import { useBecomeCreatorRouteStore } from '@/store/become-creator-route'
import HeadContainer from '@/components/layout/HeadContainer.vue'
import { BECOME_CREATOR_PHOTO_TYPE, BECOME_CREATOR_ROUTES } from '@/constant'

const routeStore = useBecomeCreatorRouteStore()
const { back } = routeStore
const { now } = storeToRefs(routeStore)

const dataStore = useBecomeCreatorDataStore()
const { identityPhoto, facePhoto, photoType } = storeToRefs(dataStore)

/**
 * @link(https://github.com/BastiaanJansen/simple-vue-camera#basics)
 */
const camera = ref(null)

const onLoading = () => console.log('camera is loading')
const onStopped = () => console.log('camera is stopped')
const onPaused = () => console.log('camera is paused')
const onResumed = () => console.log('camera is resumed')
const onCameraChanged = () => console.log('camera is changed')
const onError = () => console.log('camera is error')

const topContainer = ref()
const bottomContainer = ref()

const onSnapshot = async (data) => {
  const blob = isMobile.value ? await cropBlob(data) : data
  switch (photoType.value) {
    case BECOME_CREATOR_PHOTO_TYPE.FACE:
      facePhoto.value = blob
      break
    case BECOME_CREATOR_PHOTO_TYPE.IDENTITY:
      identityPhoto.value = blob
      break
    default:
      throw new Error('Invalid photo type')
  }
  back()
}

const goBack = () => {
  camera.value.stop()
  back()
}

// 如果是行動裝置就需要裁切照片
const cropBlob = async (blob) => {
  const { width } = camera.value.resolution

  // 頂部Container的div
  const topRect = topContainer.value.getBoundingClientRect()

  // 底部Container的div
  const bottomRect = bottomContainer.value.getBoundingClientRect()

  // 照相機div高度
  const videoRect = camera.value.video.getBoundingClientRect()

  // 照相機div高度 - 頂部Container的div高度 - 底部Container的div高度 = 照片的高度
  const viewportHeight = videoRect.height - topRect.height - bottomRect.height

  const image = new Image()
  image.src = URL.createObjectURL(blob)

  await new Promise((resolve) => {
    image.onload = () => resolve()
  })

  const canvas = document.createElement('canvas')

  // 裁切照片的寬高
  const cutWidth = 16.875 * 16 * 6
  const cutHeight = 10.625 * 16 * 6

  canvas.width = cutWidth
  canvas.height = cutHeight

  const context = canvas.getContext('2d')
  context.drawImage(image, 0, topRect.bottom + bottomRect.height, width, viewportHeight, 0, 0, cutWidth, cutHeight)

  const result = new Promise((resolve) => {
    canvas.toBlob((blob) => resolve(blob), 'image/jpeg')
  })
  return result
}

watch(now, (value) => (value === BECOME_CREATOR_ROUTES.PHOTO_CAPTURE ? camera.value.start() : camera.value.stop()))

onMounted(() => camera.value.start())

const isMobile = computed(() =>
  /Mobi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
)

const devices = ref([])
const onStarted = async () => {
  devices.value = await camera.value?.devices(['videoinput'])
  console.log('camera', camera.value)
}

// const showFlipCamera = computed(() => devices.value.length > 1)
const isFirstDevice = computed(() => camera.value?.currentDeviceID() === devices.value[0]?.deviceId)

const flipCamera = () => {
  if (devices.value.length <= 1) return
  const deviceId = isFirstDevice.value ? devices.value[1].deviceId : devices.value[0].deviceId
  camera.value.changeCamera(deviceId)
}

const flipMirror = () => {
  if (!camera.value?.video) return
  const isFlipped = camera.value.video.style.transform === 'scaleX(-1)'
  camera.value.video.style.transform = isFlipped ? 'scaleX(1)' : 'scaleX(-1)'
}
</script>
<style scoped lang="scss">
.center {
  height: calc(100vh - 10rem);
  width: 100%;
}

.controller {
  width: 100%;
  position: absolute;
  bottom: 25%;

  display: flex;
  justify-content: space-between;
  align-items: center;
}

.capture-button {
  height: 3rem;
  width: 3rem;

  border-radius: 50rem;
  // border: 0.125rem solid var(--color-primary-red, #f42c52);
  // background: var(--bg-dialog, #3335464a);
}

.top-container {
  position: absolute;
  top: 0;

  width: 100%;
  height: 20%;
  flex-shrink: 0;

  fill: rgba(24, 25, 37, 0.5);
  backdrop-filter: blur(9px);
}

.bottom-container {
  position: absolute;
  bottom: 10%;

  width: 100%;
  height: 25%;

  fill: rgba(24, 25, 37, 0.2);
  backdrop-filter: blur(9px);
}
</style>
